#include "PasswordUtils.h"
#include <bcrypt/bcrypt.h>
#include <iostream>

namespace plugins {
// 生成哈希值（自动加盐）
    std::string PasswordUtils::hashPassword(const std::string& password) {
        char salt[BCRYPT_HASHSIZE];
        bcrypt_gensalt(12, salt);  // 12 是工作因子（值越大越安全，耗时越长）
        char hash[BCRYPT_HASHSIZE];
        bcrypt_hashpw(password.c_str(), salt, hash);
        return std::string(hash);
    }

    // 验证密码
    bool PasswordUtils::verifyPassword(const std::string& password, const std::string& saved) {
        if (isOldPW(saved)) {
            std::string mpw;
            if (!isOldPW(password)) {
                mpw = md5(password);
            } else {
                mpw = password;
            }
            
            return (mpw == saved);
        }
        
        // 新密码格式处理
        std::string svd = base64_decode(saved);
        if (svd.length() < 20) return false;
        
        std::string salt = svd.substr(20);
        std::string pwd_to_hash;
        
        if (!isOldPW(password)) {
            pwd_to_hash = md5(password);
        } else {
            pwd_to_hash = password;
        }
        
        std::string combined = pwd_to_hash + salt;
        std::string hash_raw = sha1_bin(combined);
        std::string hash_with_salt = hash_raw + salt;
        std::string hash_encoded = base64_encode(hash_with_salt);
        
        return (hash_encoded == saved);
    }

    // 辅助函数：判断是否为旧密码格式（32位十六进制字符串）
    bool PasswordUtils::isOldPW(const std::string& password) {
        if (password.length() != 32) return false;
    
        for (char c : password) {
            if ((c >= '0' && c <= '9') || 
                (c >= 'a' && c <= 'f') || 
                (c >= 'A' && c <= 'F')) {
                continue;
            }
            return false;
        }
        return true;
    }

    // 辅助函数：计算字符串的MD5哈希（返回32位小写十六进制，对应PHP的md5()）
    std::string PasswordUtils::md5(const std::string& input) {
        EVP_MD_CTX* context = EVP_MD_CTX_new();
        const EVP_MD* md = EVP_md5();
        unsigned char digest[MD5_DIGEST_LENGTH];
        unsigned int digest_len;
        
        EVP_DigestInit_ex(context, md, NULL);
        EVP_DigestUpdate(context, input.c_str(), input.length());
        EVP_DigestFinal_ex(context, digest, &digest_len);
        EVP_MD_CTX_free(context);
        
        std::stringstream ss;
        for (unsigned int i = 0; i < digest_len; i++) {
            ss << std::hex << std::setw(2) << std::setfill('0') << (int)digest[i];
        }
        
        return ss.str();
    }

    // 辅助函数：Base64编码（对应PHP的base64_encode()）
    std::string PasswordUtils::base64_encode(const std::string& input) {
        const auto base64_mime = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
    
        std::string output;
        int val = 0;
        int valb = -6;
        
        for (unsigned char c : input) {
            val = (val << 8) + c;
            valb += 8;
            while (valb >= 0) {
                output.push_back(base64_mime[(val >> valb) & 0x3F]);
                valb -= 6;
            }
        }
        
        if (valb > -6) {
            output.push_back(base64_mime[((val << 8) >> (valb + 8)) & 0x3F]);
        }
        
        while (output.size() % 4) {
            output.push_back('=');
        }
        
        return output;
    }

    // 辅助函数：Base64解码（对应PHP的base64_decode()）
    std::string PasswordUtils::base64_decode(const std::string& input) {
        const std::string base64_chars = 
        "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
        "abcdefghijklmnopqrstuvwxyz"
        "0123456789+/";
    
        std::string output;
        std::vector<int> T(256, -1);
        for (int i = 0; i < 64; i++) {
            T[base64_chars[i]] = i;
        }
        
        int val = 0, valb = -8;
        for (unsigned char c : input) {
            if (T[c] == -1) break;
            val = (val << 6) + T[c];
            valb += 6;
            if (valb >= 0) {
                output.push_back(char((val >> valb) & 0xFF));
                valb -= 8;
            }
        }
        
        return output;
    }

    // 辅助函数：计算字符串的SHA1哈希（返回二进制结果，对应PHP的sha1($str, true)）
    std::string PasswordUtils::sha1_bin(const std::string& input) {
        EVP_MD_CTX* context = EVP_MD_CTX_new();
        const EVP_MD* md = EVP_sha1();
        unsigned char digest[SHA_DIGEST_LENGTH];
        unsigned int digest_len;
        
        EVP_DigestInit_ex(context, md, NULL);
        EVP_DigestUpdate(context, input.c_str(), input.length());
        EVP_DigestFinal_ex(context, digest, &digest_len);
        EVP_MD_CTX_free(context);
        
        return std::string(reinterpret_cast<char*>(digest), digest_len);
    }
}  // namespace utils